首页 / 技术类 / 设计 / ASP.NET MVC 框架入门——写一个搜索引擎

ASP.NET MVC 框架入门——写一个搜索引擎

2013-01-08 01:54:00

动态网页的历史非常悠久,可以追溯到上个世纪。就技术类型而言,主要有ASP、PHP、JSP三大派。笔者接触过ASP、PHP,遗憾的是几乎从未接触过JSP。偶就天生不是JAVA语系的。

后来,笔者稍微远离了一下Web开发,Web发生了翻天覆地的变化,css成了布局主流,ASP.NET冒出来了。这使得笔者不得不在2008、2009年间重新进入Web开发领域。然后,自认为已经跟上时代了,于是又稍微远离了Web开发。短短两三年,PHP几乎啥也没变,HTML基本未变(虽然冒出了个HTML5),但ASP.NET却发生了翻天覆地的变化:官方MVC框架的推出,使得ASP.NET再也不用使用很别扭的服务端控件了,将自由操控HTML的权利还给了开发者(然而,却剥夺了自由操控URL的权利)。

下面,笔者以写一个搜索引擎为例,带大家进入ASP MVC 框架的世界。

建立项目

如下图,在VS2012中建立一个ASP.NET MVC4 Web Application:

然后选Basic吧:

试图引擎按默认选择Razor吧。

建好之后,我们将看到如下的项目结构:

其中Views放各种页面,Content放css啥的,Controllers放“控制器”代码,Models里放各种业务模型的数据结构定义。

URL规划

这个MVC框架的一个越俎代庖的事情就是接管了URL路由。嗯,其实也蛮方便的,叫越俎代庖有点过了,仁者见仁智者见智吧。

打开RouteConfig.cs,我肯可以看到:

 1public class RouteConfig
 2{
 3    public static void RegisterRoutes(RouteCollection routes)
 4    {
 5        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 6
 7        routes.MapRoute(
 8            name: "Default",
 9            url: "{controller}/{action}/{id}",
10            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
11        );
12    }
13}

这里有个默认的路由。比如一段http://www.xxx.com/a/b/c/,按照这个route的解释,a就是controller的名字,b就是action的名字,c就是id的名字。如果访问http://www.xxx.com/a/,那么a是controller的名字,action和id未给出,就按照default中的设定,action为Index,id为空。

说到这里,还没解释action是啥,id是啥呢。按照我们很久以前的url规划习惯,经常有article.aspx?action=modify&id=1这样子的url,controller的概念就是这里的acticle.aspx,表示文章处理的页面/模块;action就是url的query string中的action,一个处理模块通常由多个功能,action参数告诉它现在需要处理什么;id含有通常是跟随action而定的,比如刚才的例子,id表示要处理哪篇文章。

我们规划搜索引擎的URL吧:

路径 页面内容
/ 首页
/keyword 搜索结果页

于是我们可以将上面的路由代码改为:

 1public class RouteConfig
 2{
 3    public static void RegisterRoutes(RouteCollection routes)
 4    {
 5        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 6
 7        routes.MapRoute(
 8            name: "HomePage",
 9            url: "",
10            defaults: new { controller = "Home", action = "Index" }
11        );
12
13        routes.MapRoute(
14            name: "SearchResult",
15            url: "{keyword}",
16            defaults: new { controller = "Home", action = "Search", keyword = UrlParameter.Optional }
17        );
18    }
19}

注意,我们使用了一个名为Home的controler,以及名为Index、Search的两个action,Search这个action带参数keyword。

建立相应的代码和页面

建立controller

右键单击Controllers目录,选择Add=>Controller:

输入名字HomeController,选择模版类型为Empty MVC controller:

注意,必须使用这个名字!因为我们之前在URL路由中设置的Controller名字是Home。

建好后得到一个比较简单的代码,将其改造成如下的样子:

 1public class HomeController : Controller
 2{
 3    //
 4    // GET: /
 5
 6    public ActionResult Index()
 7    {
 8        return View();
 9    }
10
11    //
12    // GET: /keyword
13
14    public ActionResult Search(string keyword)
15    {
16        return View();
17    }
18}

建立View

右键单击View目录,新建子目录Home(一定要与controller同名),然后右键单击Home目录,选择Add=>View:

名字改为Index,其余默认:

注意,必须为Index,与action保持同名。然后用同样方法建立一个Search页面。

到现在为止,我们的网站可以跑了!访问根目录:

访问搜索结果页面:

建立搜索结果

建立model

考虑到搜索结果中,controller处理后需要把结果传递给页面,我们建立一个model类来表示这个数据结构。右键单击Models目录,新建一个C#代码文件,定义如下类型:

 1namespace SearchEngine.Models
 2{
 3    public class SearchResultItem
 4    {
 5        public string Title { get; set; }
 6        public string Link { get; set; }
 7        public string Description { get; set; }
 8    }
 9
10    public class SearchResult
11    {
12        public string Keyword { get; set; }
13        public List<SearchResultItem> Results { get; set; }
14    }
15}

改造controller

改写controller中的Search方法,改成:

 1public ActionResult Search(string keyword)
 2{
 3    if (keyword == null)
 4    {
 5        return RedirectToAction("Index");
 6    }
 7
 8    Models.SearchResult result = new Models.SearchResult();
 9    result.Keyword = keyword;
10    result.Results = new List<Models.SearchResultItem>();
11
12    for (int i = 0; i < 10; ++i)
13    {
14        Models.SearchResultItem item = new Models.SearchResultItem();
15        item.Link = "http://www.streamlet.org/";
16        item.Title = "溪流软件工作室";
17        item.Description = "快来访问溪流软件工作室!";
18
19        result.Results.Add(item);
20    }
21
22    return View(result);
23}

注意,我们建立了数据result,通过View(result)传递给页面。

改造View

改写Search.cshtml,改为:

 1@model SearchEngine.Models.SearchResult
 2@{
 3    ViewBag.Title = "Search";
 4}
 5
 6<h2>Search</h2>
 7
 8<p>搜索“@Model.Keyword”的结果:</p>
 9
10@foreach (var item in Model.Results)
11{
12<p>
13    <a href="@item.Link" target="_blank">@item.Title</a><br />
14    @item.Description
15</p>
16}

第一行@model声明本页面的数据模型。后面@开头的都是C#语句,剩余的是HTML。大多数情况下,Razor能识别@的结束,这比<% %>、书写起来都简洁一点。

再访问一下搜索结果页:

美化及搜索框处理

这部分利用HTML的知识和PS功底即可。我这里简单的放了一个Logo和搜索框。首页代码如下:

 1@{
 2    ViewBag.Title = "世界第一搜索引擎";
 3}
 4
 5@Styles.Render("~/Content/Index.css")
 6
 7@section scripts {
 8    <script type="text/javascript">
 9        var search = function ()
10        {
11            var keyword = $("#keyword").val();
12            window.location = "/" + keyword;
13        }
14    </script>
15}
16
17<br />
18<br />
19<br />
20<br />
21<br />
22<br />
23<br />
24
25<div id="searchBox">
26    <img src="~/Images/Logo.png" /><br />
27    <br />
28    <input id="keyword" type="text" />
29    <input id="submit" type="submit" value="搜索" onclick="javascript: search();" />
30</div>

页面效果如下:

搜索结果页面代码如下:

 1@model SearchEngine.Models.SearchResult
 2@{
 3    ViewBag.Title = "Search";
 4}
 5
 6@Styles.Render("~/Content/Search.css")
 7
 8@section scripts {
 9    <script type="text/javascript">
10        var search = function ()
11        {
12            var keyword = $("#keyword").val();
13            window.location = "/" + keyword;
14        }
15    </script>
16}
17
18<div id="searchBox">
19    <a href="/"><img src="~/Images/Logo.png" /></a><br />
20    <input id="keyword" type="text" value="@Model.Keyword" />
21    <input id="submit" type="submit" value="搜索" onclick="javascript: search();" />
22</div>
23
24<br />
25
26@foreach (var item in Model.Results)
27{
28<p>
29    <a href="@item.Link" target="_blank">@item.Title</a><br />
30    @item.Description
31</p>
32}

页面效果如下:

无搜索数据时的处理

目前,我们在Search方法中生成的数据是假的。实际情况中要根据实际结果来。当没有数据的时候,我们要给出友好提示。

因此,将controller中Search方法改为:

 1public ActionResult Search(string keyword)
 2{
 3    if (keyword == null)
 4    {
 5        return RedirectToAction("Index");
 6    }
 7
 8    Models.SearchResult result = new Models.SearchResult();
 9    result.Keyword = keyword;
10    result.Results = new List<Models.SearchResultItem>();
11
12    //for (int i = 0; i < 10; ++i)
13    //{
14    //    Models.SearchResultItem item = new Models.SearchResultItem();
15    //    item.Link = "http://www.streamlet.org/";
16    //    item.Title = "溪流软件工作室";
17    //    item.Description = "快来访问溪流软件工作室!";
18
19    //    result.Results.Add(item);
20    //}
21
22    return View(result);
23}

Search页面相应地改为:

 1@model SearchEngine.Models.SearchResult
 2@{
 3    ViewBag.Title = "Search";
 4}
 5
 6@Styles.Render("~/Content/Search.css")
 7
 8@section scripts {
 9    <script type="text/javascript">
10        var search = function ()
11        {
12            var keyword = $("#keyword").val();
13            window.location = "/" + keyword;
14        }
15    </script>
16}
17
18<div id="searchBox">
19    <a href="/"><img src="~/Images/Logo.png" /></a><br />
20    <input id="keyword" type="text" value="@Model.Keyword" />
21    <input id="submit" type="submit" value="搜索" onclick="javascript: search();" />
22</div>
23
24<br />
25
26@if (Model.Results == null || Model.Results.Count() == 0)
27{
28    <strong>根据相关法律法规和政策,部分搜索结果未予显示。</strong>
29}
30else
31{
32    foreach (var item in Model.Results)
33    {
34<p>
35    <a href="@item.Link" target="_blank">@item.Title</a><br />
36    @item.Description
37</p>
38    }
39}

页面效果:

例子代码:http://pan.baidu.com/s/1o6r5Qga(SearchEngine.rar)
演示页面:http://www.streamlet.org/Search/


首发:http://www.cppblog.com/Streamlet/archive/2013/01/08/197092.html



NoteIsSite/0.4